import Grass from './grass.js'
import Water from './water.js'
import Wall from './Wall.js'
import Tank from './tank.js'
import Direction from './direction.js'
import EnemyTank from './EnemyTank.js'
import Destriable from './Destriable.js'

var _instance = null

export default class Game {
  constructor(context) {
    if (_instance) {
      return _instance
    }
    _instance = this
    this.playerRockets = []
    this.enemyRockets = []
    this.context = context
    this.score = 0
    this.AITanks = []
  }

  initMap() {
    this.mapData = []
    for (var i = 0; i < 16; i++) {
      for (var j = 0; j < 12; j++) {
        var block
        var r = Math.random() * 100
        if (r < 80) {
          block = new Grass(i * 50, j * 50)
        } else if (r < 87) {
          block = new Water(i * 50, j * 50)
        } else {
          block = new Wall(i * 50, j * 50)
          block.event.add('onDestroy', wall => {
            let { x, y } = wall
            let index = this.mapData.indexOf(wall)
            this.mapData[index] = new Grass(x, y)
          })
        }
        this.mapData.push(block)
      }
    }
  }

  initPlayer() {
    var { x, y } = this.mapData[119]
    this.mapData[119] = new Grass(x, y)
    this.playerTank = new Tank(x, y)
    this.playerTank.event.add('onDamage', tank => {
      if (tank.life <= 0) {
        // clearInterval(this.timer);
        this.gameOver()
      }
    })
    this.playerTank.shootInterval = 200
  }

  killEnemy(tank) {
    let index = this.AITanks.indexOf(tank)
    this.AITanks.splice(index, 1)
    this.score += 10
  }

  createAITank(index) {
    var { x, y } = this.mapData[index]
    var ai = new EnemyTank(x, y)
    this.mapData[index] = new Grass(x, y)
    ai.event.add('onDestroy', this.killEnemy)
    this.AITanks.push(ai)
  }

  initAITank() {
    this.createAITank(0)
    this.createAITank(180)
  }

  initGame() {
    this.initMap()
    this.initPlayer()
    this.initAITank()
    this.enemyTimer = setInterval(() => {
      this.initAITank()
    }, 5000)
  }

  renderMap() {
    this.mapData.forEach(e => {
      e.render(this.context)
    })
  }
  renderTank() {
    this.playerTank.render(this.context)
    this.playerTank.drawLifeBar(this.context)
    this.AITanks.forEach(e => {
      e.render(this.context)
      e.drawLifeBar(this.context)
    })
  }

  renderRockets() {
    this.playerRockets.forEach(e => {
      e.render(this.context)
    })

    this.enemyRockets.forEach(e => {
      e.render(this.context)
    })
  }

  render(context) {
    // 先清除之前的
    context.clearRect(0, 0, 800, 600)
    // context.fillStyle = 'rgba(0,0,0,0.01)'
    // context.rect(0, 0, 800, 600)
    // context.fill()

    // this.context.globalCompositeOperation = 'destination-out'
    // this.context.fillStyle = 'rgba(0,0,0,' + 10 / 100 + ')'
    // this.context.fillRect(0, 0, 800, 600)
    // this.context.globalCompositeOperation = 'lighter'

    // 渲染地图
    this.renderMap()
    // 渲染子弹
    this.renderRockets()
    // 渲染坦克
    this.renderTank()
  }

  movePlayerTank(cols) {
    if (this.controlKeys.length > 0) {
      var first = this.controlKeys[0]
      var dir = 0
      switch (first) {
        // w
        case 87:
          dir = Direction.TOP
          break
        // a
        case 65:
          dir = Direction.LEFT
          break
        // s
        case 83:
          dir = Direction.DOWN
          break
        // d
        case 68:
          dir = Direction.RIGHT
          break
      }

      // console.log(cols)
      this.playerTank.move(dir, cols)
    }
  }

  moveEnemyTank(cols) {
    this.AITanks.forEach((e, i) => {
      e.autoMove(cols)
      if (e.life <= 0) {
        this.AITanks.splice(i, 1)
      }
    })
  }

  movePlayerRockets(cols) {
    this.playerRockets.forEach((e, i) => {
      e.autoMove(cols)
    })
  }
  moveEnemyRockets(cols) {
    this.enemyRockets.forEach(e => {
      e.autoMove(cols)
    })
  }

  updateMap() {
    this.mapData.forEach((e, i) => {
      if (e instanceof Destriable && e.life <= 0) {
        let { x, y } = e
        let g = new Grass(x, y)
        this.mapData[i] = g
      }
    })
  }

  loop() {
    this.timer = setInterval(() => {
      this.render(this.context)
      var cols = this.mapData.filter(e => e.passable === false)
      // 移动玩家坦克
      this.movePlayerTank(cols.concat(this.AITanks))
      // 移动AI坦克
      this.moveEnemyTank(cols.concat(this.playerTank))
      // 玩家坦克射击
      if (this.playerTankFire && this.playerTank.readyShoot) {
        let r = this.playerTank.shoot()
        r.event.add('onDestory', r => {
          let index = this.playerRockets.indexOf(r)
          index !== -1 && this.playerRockets.splice(index, 1)
        })
        this.playerRockets.push(r)
      }

      // 敌人射击
      this.AITanks.forEach(e => {
        if (!e.readyShoot) return
        let r = e.shoot()
        r.event.add('onDestory', r => {
          let index = this.enemyRockets.indexOf(r)
          index !== -1 && this.enemyRockets.splice(index, 1)
        })
        this.enemyRockets.push(r)
      })

      // 移动玩家子弹
      this.movePlayerRockets(cols.filter(e => e.overable === false).concat(this.AITanks))
      // 移动敌人子弹
      this.moveEnemyRockets(cols.filter(e => e.overable === false).concat(this.playerTank))
    }, 20)
  }

  start() {
    this.loop()
    this.bindKey()
  }

  bindKey() {
    this.controlKeys = []
    document.addEventListener('keydown', e => {
      // console.log(e.keyCode)
      var code = e.keyCode
      if (code == 87 || code == 65 || code == 83 || code == 68) {
        if (this.controlKeys.indexOf(code) == -1) {
          this.controlKeys.unshift(code)
        }
      }
      code === 32 && (this.playerTankFire = true)
    })

    document.addEventListener('keyup', e => {
      var index = this.controlKeys.indexOf(e.keyCode)
      if (index !== -1) {
        this.controlKeys.splice(index, 1)
      }
      e.keyCode === 32 && (this.playerTankFire = false)
    })
  }

  gameOver() {
    this.context.font = '160px Arial'
    this.context.fillStyle = 'red'
    this.context.fillText('游戏结束', 80, 300)
    clearInterval(this.timer)
  }
}
